﻿using System;
using System.Collections.Generic;
using System.Text;

using PostSharp.Laos;
using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using System.Reflection;

namespace EntlibAOP.Security.Cryptography
{
    [Serializable]
    [AttributeUsage(AttributeTargets.Method)]
    public class DecryptionAttribute : OnMethodInvocationAspect 
    {
        private string currConfigSetting;
        private string parameterIndexes;

        string argnames;

        /// <summary>
        /// This property represent the name of the configuration setting which contain the cryptography 
        /// configuration information
        /// </summary>
        public string ConfigSettingName
        {
            get;
            set;
        }

        /// <summary>
        /// This property represent the collection of parameter names to be encrypted
        /// </summary>
        public string[] ParameterNames
        {
            get;
            set;
        }

        /// <summary>
        /// This method is used to store the indexes of the parameters to be decrypted
        /// </summary>
        /// <param name="method">Argument that represent the method</param>
        public override void CompileTimeInitialize(MethodBase method)
        {
            ParameterInfo[] parameters = method.GetParameters();
            
            foreach (string param in ParameterNames)
            {
                
                for (int i = 0; i < parameters.Length; i++)
                {
                    argnames += parameters[i].Name + ",";
                    if (parameters[i].Name.Equals(param, StringComparison.InvariantCulture))
                    {
                        parameterIndexes += i.ToString() + ",";
                    }
                }
            }
            parameterIndexes = parameterIndexes.Substring(0, parameterIndexes.Length - 1);
        }

        /// <summary>
        /// This method is used to intercept the method invocation and supply the method with the 
        /// decrypted parameter values
        /// </summary>
        /// <param name="eventArgs">Argument passed to the event handler</param>
        public override void OnInvocation(MethodInvocationEventArgs eventArgs)
        {
            if (string.IsNullOrEmpty(ConfigSettingName))
            {
                throw new Exception("InValid Configuration");
            }

            object[] args = eventArgs.GetArgumentArray();
            string[] paramindexarray = parameterIndexes.Split(',');
            foreach (string index in paramindexarray)
            {
                object arg = args[Convert.ToInt32(index)];
                args[Convert.ToInt32(index)] = Cryptographer.DecryptSymmetric(ConfigSettingName, arg.ToString());
            }
            eventArgs.Proceed();
        }
    }
}
